[Home] Python으로 돌아가기

NumPy-2: 연산, 브로드캐스트, 복사

목차

참조 자료

(3) 연산

(4) 브로드캐스트

(5) 복사

참조 자료

(3) 연산

1) 요소별 연산

import numpy as np
A = np.array([1,2])
B = np.array([4,5])
print(A + B)  # array([5,7])
print(A * B)  # array([4,10])
print(A ** 2) # array([1,4])
print(A + 2)  # array([3,4])
10*np.sin(A)  # 각 요소에 sin() 적용; array( [8.41470985,9.09297427] )
A<3   # array([ True,True ], dtype=bool)
A *= B # A = A*B와 동일; B와 곱한 다음에 A에 저장; array( [4,10] )
A[0:2,] # array( [4,10] )

2) Universal 함수

NumPy는 수학 함수 np.sin(), np.cos() 등을 제공한다.

스칼라값을 입력으로 하는 math 패키지와 달리 배열에 대해 elementwise로(즉, 각 요소에 대해) 적용된다.


import numpy as np
x = np.arange(0.,np.pi,1.) # array( [0.,1.,2.,3.] )
y = np.sin(x) # array( [0., 0.84147098, 0.90929743, 0.14112001] )
    

3) 행렬 연산


import numpy as np

A = np.arange(4).reshape(2,2)      # (2,2); array( [[0,1],[2,3]] )
B = np.arange(5,5+4).reshape(2,2)  # (2,2); array( [[5,6],[7,8]] )

X = np.arange(2)                   # (2,); array( [0,1] )
Y = np.arange(2).reshape(2,1)      # (2,1); array( [[0],[1]] )
Z = np.arange(2).reshape(1,2)      # (1,2); array( [[0,1]] )

# A*B, (2,2)*(2*2) = (2,2), 같은 결과
C1 = np.dot(A,B)     # array( [[7,8],[31,36]] )
C2 = np.matmul(A,B)  # array( [[7,8],[31,36]] )
C3 = A@B             # array( [[7,8],[31,36]] )

# A*X, (2,2)*(1*2) = (1,2), 같은 결과
AX1 = np.dot(A,X)    # array( [1,3] )
AX2 = np.matmul(A,X) # array( [1,3] )
AX3 = A@X            # array( [1,3] )

# A*Y, (2,2)*(2*1) = (2,1), 같은 결과 
AY1 = np.dot(A,Y)    # array( [[1],[3]] )
AY2 = np.matmul(A,Y) # array( [[1],[3]] ) 
AY3 = A@Y            # array( [[1],[3]] ) 

# A*Z, (2,2)*(1*2) = (1,2), 행렬 차수 에러
AZ1 = np.dot(A,Z)     
AZ2 = np.matmul(A,Z)  
AZ3 = A@Z            

# X*Y, (1,2)*(2*1) = (1,2)
XY = X@Y   # array([1])

#전치행렬(transpose matrix)
A.T             # array( [[0, 2],[1, 3]] )
np.transpose(A) # array( [[0, 2],[1, 3]] )

# 선형대수함수
A = np.array( [[1,2],[3,7]] )
[D,V] = np.linalg.eig(A)   # D = eigenvalues, V = eigen vectors

#언팩킹(unpacking): *(asterisk)를 사용
np.array([0,60,40,20,0,np.zeros(n-5)])  --> array([0, 60, 40, 20, 0, array([0., 0., 0., ..., 0., 0., 0.])], dtype=object)
np.array([0,60,40,20,0,*np.zeros(n-5)]) --> array([ 0., 60., 40., ...,  0.,  0.,  0.])
    

4) 정렬과 탐색


import numpy as np

X = np.array( [9.1,8.2,2.3] )

np.amin(X) # 최솟값, 2.3
np.amax(X) # 최댓값, 9.1

np.argmin(X) # 최솟값 위치, 2
np.argmax(X) # 최댓값 위치, 0

np.sort(X) # 오름차순 정렬, array( [2.3,8.2,9.1] )
np.argsort(X) # 오름차순 정렬 위치, array([2, 1, 0], dtype=int64)

np.argsort(X)[0]  # 가장 작은 값의 위치, 2
np.argsort(X)[-1] # 가장 큰 값의 위치, 0
np.argsort(X)[-2] # 두 번째로 큰 값의 위치, 1
    

(4) 브로드캐스트

형태가 다른 행렬의 연산


import numpy as np

A = np.arange(4.).reshape(2,2) # 2D array, (2,2), array( [[0.,1.],[2.,3.]] )
X = np.array( [1.,0.] )        # 1D array, (2,) , array( [1.,0.] )
Y = X.reshape(1,2)             # 2D array, (1,2), array( [[1.,0.]] )
Z = X.reshape(2,1)             # 2D array, (2,1), array( [[1.],[0.]] )

A+1  # (2,2) + scalar*I = (2,2); array( [[1.,2.],[3.,4.]] )
A+X  # (2,2) + (2,) = (2,2); array( [[1.,1.], [3.,3.]])
A+Y  # (2,2) + (1,2) = (2,2); array( [[1.,1.], [3.,3.]])
A+Z  # (2,2) + (2,1) = (2,2); array( [[1.,2.], [2.,3.]])
https://blog.finxter.com/numpy-broadcasting-a-simple-tutorial/
https://gomguard.tistory.com/146

행렬 연산 함수 호출시 주의사항


import numpy as np

A = np.arange(4.).reshape(2,2) # 2D array, (2,2), array( [[0.,1.],[2.,3.]] )
X = np.array( [1.,0.] )        # 1D array, (2,) 
Y = X.reshape(1,2)             # 2D array, (1,2)
Z = X.reshape(2,1)             # 2D array, (2,1)

np.matmul(A,Y)   # (2,2)*(1,2) = Dimension Error
np.matmul(A,Z)   # (2,2)*(2,1) = (2,1), array( [[0.],[2.]] )
np.matmul(A,X)   # (2,2)*(2,) = (2,), array( [0.,2.] )
    

(5) 복사

1) 얕은 복사 vs 깊은 복사

깊은 복사(deep copy): 서로 값만 같을 뿐 본질적으로 서로 다르기 때문에 한 변수가 수정될 시 다른 변수가 수정되지 않는다.

얕은 복사(shallow copy): 서로 다른 변수명이지만 본질적으로 서로 같은 대상을 의미하므로 하나의 변수 역시 수정이 된다.


import numpy as np

A = [1,2,3]     # [1, 2, 3]
X = np.array(A) # array( [1, 2, 3] )

Z = X.copy()    # deep copy
Z is X          # False

Y = X           # shallow copy
Y[0] = 10       # 

X               # array( [10, 2, 3] )
Y               # array( [10, 2, 3] )

Y is X          # True
X is Y          # True
    

2) 부분행렬 복사

부분행렬은 얕은 복사이다.


import numpy as np
X = np.array( [1,2,3] )

Y = X[0:2]      # shallow copy
Y[0] = 10       #

Y               # array( [10,2] )
X               # array( [10,2,3] )